package com.ssy.lingxi.marketing.serviceimpl.component.activity;

import com.querydsl.core.BooleanBuilder;
import com.querydsl.core.types.Projections;
import com.querydsl.jpa.impl.JPAQuery;
import com.querydsl.jpa.impl.JPAQueryFactory;
import com.ssy.lingxi.common.constant.marketing.BelongTypeEnum;
import com.ssy.lingxi.common.model.bo.MemberAndRoleIdBO;
import com.ssy.lingxi.common.response.ResponseCode;
import com.ssy.lingxi.common.response.Wrapper;
import com.ssy.lingxi.marketing.entity.activity.QActivityGoodsDO;
import com.ssy.lingxi.marketing.entity.activity.QActivityShopDO;
import com.ssy.lingxi.marketing.entity.activity.QMerchantActivityDO;
import com.ssy.lingxi.marketing.entity.activity.QPlatformActivityDO;
import com.ssy.lingxi.marketing.model.bo.ActivityGoodsBO;
import com.ssy.lingxi.marketing.model.bo.ActivityGoodsDetailBO;
import com.ssy.lingxi.marketing.model.bo.MerchantActivityBO;
import com.ssy.lingxi.marketing.model.bo.PlatformActivityBO;
import com.ssy.lingxi.marketing.model.constant.ActivityGoodsAuditStatusEnum;
import com.ssy.lingxi.marketing.model.constant.MerchantActivityInnerStatusEnum;
import com.ssy.lingxi.marketing.model.constant.PlatformActivityOuterStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * 商品活动查询组件
 * @author yzc
 * @version 2.0.0
 * @date 2021/11/22
 */
@Slf4j
@Component
public class ActivityQueryComponent {

    @Resource
    private JPAQueryFactory queryFactory;
    @Resource
    private ActivityCheckRuleComponent activityCheckRuleComponent;
    @Resource
    private ActivityPriceCalculateComponent activityPriceCalculateComponent;

    /**
     * 查询当前正在进行的平台活动(根据商品id)
     * @param shopId 商城id
     * @param productIds 商品id
     * @return 返回结果
     */
    public List<ActivityGoodsDetailBO> selectPlatformActivityExecutingByProduct(Long shopId, List<Long> productIds) {
        QActivityGoodsDO goodsDO = QActivityGoodsDO.activityGoodsDO;

        BooleanBuilder predicates = this.createPlatformCommonBuilder(shopId);

        // 商品id
        if (!CollectionUtils.isEmpty(productIds)) {
            predicates.and(goodsDO.productId.in(productIds));
        }

        return this.fetchPlatformQuery(predicates);
    }

    /**
     * 查询当前正在进行的平台活动(根据商品id)
     * @param shopId 商城id
     * @param productIds 商品id
     * @return 返回结果
     */
    public List<ActivityGoodsDetailBO> selectPlatformActivityExecutingByProductAndActivity(Long shopId, List<Long> productIds, Long activityId) {
        return selectPlatformActivityExecuting(shopId,productIds,null,activityId);
    }

    /**
     * 查询当前正在进行的平台活动(根据商品id)
     * @param shopId 商城id
     * @param productIds 商品id
     * @return 返回结果
     */
    public List<ActivityGoodsDetailBO> selectPlatformActivityExecuting(Long shopId, List<Long> productIds,List<Long> skuIds, Long activityId) {
        QActivityGoodsDO goodsDO = QActivityGoodsDO.activityGoodsDO;

        BooleanBuilder predicates = this.createPlatformCommonBuilder(shopId);

        // 活动id
        if (Objects.nonNull(activityId)) {
            predicates.and(goodsDO.activityId.in(activityId));
        }

        // 商品id
        if (!CollectionUtils.isEmpty(productIds)) {
            predicates.and(goodsDO.productId.in(productIds));
        }

        // skuId
        if (!CollectionUtils.isEmpty(skuIds)) {
            predicates.and(goodsDO.skuId.in(skuIds));
        }
        return this.fetchPlatformQuery(predicates);
    }

    /**
     * 查询当前正在进行的平台活动(根据productId和skuId)
     * @param shopId 商城id
     * @param productId 商品id
     * @param skuId 商品skuId
     * @return 返回结果
     */
    public List<ActivityGoodsDetailBO> selectPlatformActivityExecutingByProductSku(Long shopId, Long productId, Long skuId) {
        QActivityGoodsDO goodsDO = QActivityGoodsDO.activityGoodsDO;

        BooleanBuilder predicates = this.createPlatformCommonBuilder(shopId);

        // productId
        if (Objects.nonNull(productId)) {
            predicates.and(goodsDO.productId.eq(productId));
        }
        // skuId
        if (Objects.nonNull(skuId)) {
            predicates.and(goodsDO.skuId.eq(skuId));
        }

        return this.fetchPlatformQuery(predicates);
    }

    /**
     * 查询当前正在进行的平台活动(根据skuId)
     * @param shopId 商城id
     * @param skuIdList 商品skuId
     * @return 返回结果
     */
    public List<ActivityGoodsDetailBO> selectPlatformActivityExecutingBySku(Long shopId, List<Long> skuIdList) {
        QActivityGoodsDO goodsDO = QActivityGoodsDO.activityGoodsDO;

        BooleanBuilder predicates = this.createPlatformCommonBuilder(shopId);

        // skuId
        if (!CollectionUtils.isEmpty(skuIdList)) {
            predicates.and(goodsDO.skuId.in(skuIdList));
        }

        return this.fetchPlatformQuery(predicates);
    }

    private BooleanBuilder createPlatformCommonBuilder(Long shopId) {
        QActivityGoodsDO goodsDO = QActivityGoodsDO.activityGoodsDO;
        QPlatformActivityDO platformActivityDO = QPlatformActivityDO.platformActivityDO;
        QActivityShopDO activityShopDO = QActivityShopDO.activityShopDO;

        BooleanBuilder predicates = new BooleanBuilder();
        // 进行中
        predicates.and(platformActivityDO.outerStatus.eq(PlatformActivityOuterStatusEnum.ONGOING.getCode()));
        // 当前时间在活动时间内
        long currentTimeMillis = System.currentTimeMillis();
        predicates.and(platformActivityDO.startTime.loe(currentTimeMillis));
        predicates.and(platformActivityDO.endTime.goe(currentTimeMillis));
        // 所属类型
        predicates.and(goodsDO.belongType.eq(BelongTypeEnum.PLATFORM.getCode()));
        // 适用商城
        predicates.and(activityShopDO.shopId.eq(shopId));
        // 商品审核通过
        predicates.and(goodsDO.auditStatus.eq(ActivityGoodsAuditStatusEnum.AGREE.getCode()));

        return predicates;
    }

    private List<ActivityGoodsDetailBO> fetchPlatformQuery(BooleanBuilder predicates) {
        QActivityGoodsDO goodsDO = QActivityGoodsDO.activityGoodsDO;
        QPlatformActivityDO platformActivityDO = QPlatformActivityDO.platformActivityDO;
        QActivityShopDO activityShopDO = QActivityShopDO.activityShopDO;

        JPAQuery<ActivityGoodsDetailBO> queryJpaQuery = queryFactory.select(
                Projections.constructor(ActivityGoodsDetailBO.class,
                        goodsDO.id,
                        goodsDO.activityId,
                        goodsDO.belongType,
                        goodsDO.productId,
                        goodsDO.skuId,
                        goodsDO.price,
                        goodsDO.preSelPrice,
                        goodsDO.plummetPrice,
                        goodsDO.activityPrice,
                        goodsDO.deductionPrice,
                        goodsDO.discount,
                        goodsDO.restrictNum,
                        goodsDO.restrictTotalNum,
                        Projections.constructor(PlatformActivityBO.class,
                                platformActivityDO.id,
                                platformActivityDO.activityType,
                                platformActivityDO.activityDefined,
                                platformActivityDO.activityName,
                                platformActivityDO.startTime,
                                platformActivityDO.endTime,
                                platformActivityDO.suitableMember,
                                platformActivityDO.suitableMemberType,
                                platformActivityDO.memberId,
                                platformActivityDO.roleId
                        )
                ))
                .from(goodsDO)
                .leftJoin(platformActivityDO).on(platformActivityDO.id.eq(goodsDO.activityId))
                .leftJoin(activityShopDO).on(activityShopDO.activityId.eq(platformActivityDO.id).and(activityShopDO.belongType.eq(BelongTypeEnum.PLATFORM.getCode())));

        queryJpaQuery.where(predicates);

        return queryJpaQuery.orderBy(platformActivityDO.createTime.desc()).fetch();
    }

    /**
     * 查询当前正在进行的商家活动(根据商品id)
     * @param shopId 商城id
     * @param productIds 商品id
     * @return 返回结果
     */
    public List<ActivityGoodsDetailBO> selectMerchantActivityExecutingByProduct(Long shopId, List<Long> productIds) {
        return selectMerchantActivityExecuting(shopId,productIds,null);
    }
    /**
     * 查询当前正在进行的商家活动(根据商品id)
     * @param shopId 商城id
     * @param skuIds 商品id
     * @return 返回结果
     */
    public List<ActivityGoodsDetailBO> selectMerchantActivityExecutingBySku(Long shopId, List<Long> skuIds) {
        return selectMerchantActivityExecuting(shopId,null,skuIds);
    }

    /**
     * 查询当前正在进行的商家活动(根据商品id)
     * @param shopId 商城id
     * @param productIds 商品id
     * @param skuIds 商品skuId
     * @return 返回结果
     */
    public List<ActivityGoodsDetailBO> selectMerchantActivityExecuting(Long shopId, List<Long> productIds, List<Long> skuIds) {
        QActivityGoodsDO goodsDO = QActivityGoodsDO.activityGoodsDO;
        BooleanBuilder predicates = this.createMerchantCommonBuilder(shopId);
        if (!CollectionUtils.isEmpty(productIds)) {
            predicates.and(goodsDO.productId.in(productIds));
        }
        if (!CollectionUtils.isEmpty(skuIds)) {
            predicates.and(goodsDO.skuId.in(skuIds));
        }

        return this.fetchMerchantQuery(predicates);
    }

    public List<ActivityGoodsDetailBO> selectMerchantActivityExecutingByProductAndActivity(Long shopId, List<Long> productIds, Long activityId) {
       return selectMerchantActivityExecuting(shopId,productIds,null,activityId);
    }

    public List<ActivityGoodsDetailBO> selectMerchantActivityExecuting(Long shopId, List<Long> productIds, List<Long> skuIds, Long activityId) {
        QActivityGoodsDO goodsDO = QActivityGoodsDO.activityGoodsDO;

        BooleanBuilder predicates = this.createMerchantCommonBuilder(shopId);

        // 活动id
        if (Objects.nonNull(activityId)) {
            predicates.and(goodsDO.activityId.eq(activityId));
        }

        if (!CollectionUtils.isEmpty(productIds)) {
            predicates.and(goodsDO.productId.in(productIds));
        }
        if (!CollectionUtils.isEmpty(skuIds)) {
            predicates.and(goodsDO.skuId.in(skuIds));
        }
        return this.fetchMerchantQuery(predicates);
    }

    /**
     * 查询当前正在进行的商家活动(根据productId和skuId)
     * @param shopId 商城id
     * @param productId 商品id
     * @param skuId 商品skuId
     * @return 返回结果
     */
    public List<ActivityGoodsDetailBO> selectMerchantActivityExecutingByProductSku(Long shopId, Long productId, Long skuId) {
        QActivityGoodsDO goodsDO = QActivityGoodsDO.activityGoodsDO;

        BooleanBuilder predicates = this.createMerchantCommonBuilder(shopId);

        // productId
        if (Objects.nonNull(productId)) {
            predicates.and(goodsDO.productId.eq(productId));
        }
        // skuId
        if (Objects.nonNull(skuId)) {
            predicates.and(goodsDO.skuId.eq(skuId));
        }

        return this.fetchMerchantQuery(predicates);
    }

    private BooleanBuilder createMerchantCommonBuilder(Long shopId) {
        QActivityGoodsDO goodsDO = QActivityGoodsDO.activityGoodsDO;
        QMerchantActivityDO merchantActivityDO = QMerchantActivityDO.merchantActivityDO;
        QActivityShopDO activityShopDO = QActivityShopDO.activityShopDO;

        BooleanBuilder predicates = new BooleanBuilder();
        // 进行中
        predicates.and(merchantActivityDO.innerStatus.eq(MerchantActivityInnerStatusEnum.ONGOING.getCode()));
        // 当前时间在活动时间内
        long currentTimeMillis = System.currentTimeMillis();
        predicates.and(merchantActivityDO.startTime.loe(currentTimeMillis));
        predicates.and(merchantActivityDO.endTime.goe(currentTimeMillis));
        // 所属类型
        predicates.and(goodsDO.belongType.eq(BelongTypeEnum.MERCHANT.getCode()));
        // 商品id
        predicates.and(activityShopDO.shopId.eq(shopId));

        return predicates;
    }

    private List<ActivityGoodsDetailBO> fetchMerchantQuery(BooleanBuilder predicates) {
        QActivityGoodsDO goodsDO = QActivityGoodsDO.activityGoodsDO;
        QMerchantActivityDO merchantActivityDO = QMerchantActivityDO.merchantActivityDO;
        QActivityShopDO activityShopDO = QActivityShopDO.activityShopDO;

        JPAQuery<ActivityGoodsDetailBO> queryJpaQuery = queryFactory.select(
                Projections.constructor(ActivityGoodsDetailBO.class,
                        goodsDO.id,
                        goodsDO.activityId,
                        goodsDO.belongType,
                        goodsDO.productId,
                        goodsDO.skuId,
                        goodsDO.price,
                        goodsDO.preSelPrice,
                        goodsDO.plummetPrice,
                        goodsDO.activityPrice,
                        goodsDO.deductionPrice,
                        goodsDO.discount,
                        goodsDO.restrictNum,
                        goodsDO.restrictTotalNum,
                        Projections.constructor(MerchantActivityBO.class,
                                merchantActivityDO.id,
                                merchantActivityDO.activityType,
                                merchantActivityDO.activityDefined,
                                merchantActivityDO.activityName,
                                merchantActivityDO.startTime,
                                merchantActivityDO.endTime,
                                merchantActivityDO.suitableUser,
                                merchantActivityDO.memberId,
                                merchantActivityDO.roleId
                        )
                ))
                .from(goodsDO)
                .leftJoin(merchantActivityDO).on(merchantActivityDO.id.eq(goodsDO.activityId))
                .leftJoin(activityShopDO).on(activityShopDO.activityId.eq(merchantActivityDO.id).and(activityShopDO.belongType.eq(BelongTypeEnum.MERCHANT.getCode())));

        queryJpaQuery.where(predicates);

        return queryJpaQuery.orderBy(merchantActivityDO.createTime.desc()).fetch();
    }

    public List<ActivityGoodsDetailBO> selectCheckActivityExecutingGoodsByProduct(MemberAndRoleIdBO memberAndRoleIdBO, Long shopId, List<Long> productIds) {
        // 平台活动商品
        List<ActivityGoodsDetailBO> platformActivityGoodsList = this.selectPlatformActivityExecutingByProduct(shopId, productIds);
        // 商家活动商品
        List<ActivityGoodsDetailBO> merchantActivityGoodsList = this.selectMerchantActivityExecutingByProduct(shopId, productIds);

        return this.mergeAndCheckActivityGoods(memberAndRoleIdBO, platformActivityGoodsList, merchantActivityGoodsList);
    }

    public List<ActivityGoodsDetailBO> selectCheckActivityExecutingGoodsByProductSku(MemberAndRoleIdBO memberAndRoleIdBO, Long shopId, Long productId, Long skuId) {
        // 平台活动商品
        List<ActivityGoodsDetailBO> platformActivityGoodsList = this.selectPlatformActivityExecutingByProductSku(shopId, productId, skuId);
        // 商家活动商品
        List<ActivityGoodsDetailBO> merchantActivityGoodsList = this.selectMerchantActivityExecutingByProductSku(shopId, productId, skuId);

        return this.mergeAndCheckActivityGoods(memberAndRoleIdBO, platformActivityGoodsList, merchantActivityGoodsList);
    }

    public List<ActivityGoodsDetailBO> selectCheckActivityExecutingGoodsByProductSku(MemberAndRoleIdBO memberAndRoleIdBO, Long shopId, Long skuId) {
        // 平台活动商品
        List<ActivityGoodsDetailBO> platformActivityGoodsList = this.selectPlatformActivityExecutingByProductSku(shopId, null, skuId);
        // 商家活动商品
        List<ActivityGoodsDetailBO> merchantActivityGoodsList = this.selectMerchantActivityExecutingByProductSku(shopId, null, skuId);

        return this.mergeAndCheckActivityGoods(memberAndRoleIdBO, platformActivityGoodsList, merchantActivityGoodsList);
    }

    private List<ActivityGoodsBO> buildActivityGoodsBOListByActivityIds(List<ActivityGoodsDetailBO> platformActivityGoodsList){
        if(!CollectionUtils.isEmpty(platformActivityGoodsList)){
            return platformActivityGoodsList.stream().map(o ->{
                ActivityGoodsBO bo=new ActivityGoodsBO();
                bo.setActivityId(o.getActivityId());
                return bo;
            }).collect(Collectors.toList());
        }
        return null;
    }

    public List<ActivityGoodsDetailBO> selectActivityExecutingGoodsBySku(Long shopId, List<Long> skuIdList,MemberAndRoleIdBO loginUser) {
        // 平台活动商品
        List<ActivityGoodsDetailBO> platformActivityGoodsList = this.selectPlatformActivityExecutingBySku(shopId, skuIdList);
        //过滤平台适应会员
        List<ActivityGoodsBO> activityGoodsBOList = buildActivityGoodsBOListByActivityIds(platformActivityGoodsList);
        if(activityGoodsBOList!=null) {
            List<ActivityGoodsBO> platformActivityDOList = activityPriceCalculateComponent.checkPlatformActivity(loginUser, activityGoodsBOList).getData();
            if(CollectionUtils.isEmpty(platformActivityDOList)){
                platformActivityGoodsList=null;
            }else{
                Set<Long> enableActivityIdList = platformActivityDOList.stream().map(o -> o.getActivityId()).collect(Collectors.toSet());
                platformActivityGoodsList.removeIf(o ->!enableActivityIdList.contains(o.getActivityId()));
            }
        }

        // 商家活动商品
        List<ActivityGoodsDetailBO> merchantActivityGoodsList = this.selectMerchantActivityExecutingBySku(shopId, skuIdList);
        //过滤商户适应会员
        activityGoodsBOList = buildActivityGoodsBOListByActivityIds(merchantActivityGoodsList);
        if(activityGoodsBOList!=null) {
            List<ActivityGoodsBO> merchantActivityDOList = activityPriceCalculateComponent.checkMerchantActivity(loginUser, activityGoodsBOList).getData();
            if(CollectionUtils.isEmpty(merchantActivityDOList)){
                merchantActivityGoodsList=null;
            }else{
                Set<Long> enableActivityIdList = merchantActivityDOList.stream().map(o -> o.getActivityId()).collect(Collectors.toSet());
                merchantActivityGoodsList.removeIf(o ->!enableActivityIdList.contains(o.getActivityId()));
            }
        }
        return mergeActivityGoods(platformActivityGoodsList, merchantActivityGoodsList);
    }

    public List<ActivityGoodsDetailBO> mergeAndCheckActivityGoods(MemberAndRoleIdBO memberAndRoleIdBO, List<ActivityGoodsDetailBO> platformActivityGoodsList, List<ActivityGoodsDetailBO> merchantActivityGoodsList) {
        Wrapper<List<ActivityGoodsDetailBO>> platformWrapper = activityCheckRuleComponent.checkPlatformActivity(memberAndRoleIdBO, platformActivityGoodsList);
        if (ResponseCode.SUCCESS.getCode() != platformWrapper.getCode()) {
            log.error("查询平台活动适用商品失败, code: {}, message: {}", platformWrapper.getCode(), platformWrapper.getMessage());
        }

        Wrapper<List<ActivityGoodsDetailBO>> merchantWrapper = activityCheckRuleComponent.checkMerchantActivity(memberAndRoleIdBO, merchantActivityGoodsList);
        if (ResponseCode.SUCCESS.getCode() != merchantWrapper.getCode()) {
            log.error("查询商家活动适用商品失败, code: {}, message: {}", merchantWrapper.getCode(), merchantWrapper.getMessage());
        }

        return mergeActivityGoods(platformWrapper.getData(), merchantWrapper.getData());
    }

    public List<ActivityGoodsDetailBO> mergeActivityGoods(List<ActivityGoodsDetailBO> platformActivityGoodsList, List<ActivityGoodsDetailBO> merchantActivityGoodsList) {
        List<ActivityGoodsDetailBO> pfGoodsList = CollectionUtils.isEmpty(platformActivityGoodsList) ? new ArrayList<>() : platformActivityGoodsList;
        List<ActivityGoodsDetailBO> mcGoodsList = CollectionUtils.isEmpty(merchantActivityGoodsList) ? new ArrayList<>() : merchantActivityGoodsList;

        pfGoodsList.addAll(mcGoodsList);

        return pfGoodsList;
    }
}

